﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using java.lang;
using java.util.concurrent;
using lineage2.commons.threading;
using Math = java.lang.Math;
using StringBuilder = java.lang.StringBuilder;

namespace Game
{
    public class ThreadPoolManager
    {
        private static long MAX_DELAY = TimeUnit.NANOSECONDS.toMillis(Long.MAX_VALUE - java.lang.System.nanoTime()) / 2;
        private static ThreadPoolManager _instance = new ThreadPoolManager();
        public static ThreadPoolManager getInstance()
        {
            return _instance;
        }
        ScheduledThreadPoolExecutor _scheduledExecutor;
	    ThreadPoolExecutor _executor;
	    private bool _shutdown;
        private ThreadPoolManager()
	    {
		    _scheduledExecutor = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_SIZE, new PriorityThreadFactory("ScheduledThreadPool", Thread.NORM_PRIORITY), new LoggingRejectedExecutionHandler());
		    _executor = new ThreadPoolExecutor(Config.EXECUTOR_THREAD_POOL_SIZE, Integer.MAX_VALUE, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue(), new PriorityThreadFactory("ThreadPoolExecutor", Thread.NORM_PRIORITY), new LoggingRejectedExecutionHandler());
		    scheduleAtFixedRate(runImpl(),300000L, 300000L);
	    }
        public RunnableImpl runImpl()
        {
            _scheduledExecutor.purge();
            _executor.purge();
            return null;
        }
        private long validate(long delay)
        {
            return Math.max(0, Math.min(MAX_DELAY, delay));
        }
        public bool isShutdown()
        {
            return _shutdown;
        }

        public Runnable wrap(Runnable r)
        {
            return Config.ENABLE_RUNNABLE_STATS ? RunnableStatsWrapper.wrap(r) : r;
        }
        public ScheduledFuture schedule(Runnable r, long delay)
	    {
		    return _scheduledExecutor.schedule(wrap(r), validate(delay), TimeUnit.MILLISECONDS);
	    }
            public ScheduledFuture scheduleAtFixedRate(Runnable r, long initial, long delay)
	    {
		    return _scheduledExecutor.scheduleAtFixedRate(wrap(r), validate(initial), validate(delay), TimeUnit.MILLISECONDS);
	    }
        public ScheduledFuture scheduleAtFixedDelay(Runnable r, long initial, long delay)
	    {
		    return _scheduledExecutor.scheduleWithFixedDelay(wrap(r), validate(initial), validate(delay), TimeUnit.MILLISECONDS);
	    }
        public void execute(Runnable r)
        {
            _executor.execute(wrap(r));
        }
        public void shutdown()
	    {
		    _shutdown = true;
		    try
		    {
			    _scheduledExecutor.shutdown();
			    _scheduledExecutor.awaitTermination(10, TimeUnit.SECONDS);
		    }
            finally
		    {
			    _executor.shutdown();
			    _executor.awaitTermination(1, TimeUnit.MINUTES);
		    }
            throw new InterruptedException();
	    }
        public CharSequence getStats()
        {
            StringBuilder list = new StringBuilder();
            list.append("ScheduledThreadPool\n");
            list.append("=================================================\n");
            list.append("\tgetActiveCount: ...... ").append(_scheduledExecutor.getActiveCount()).append('\n');
            list.append("\tgetCorePoolSize: ..... ").append(_scheduledExecutor.getCorePoolSize()).append('\n');
            list.append("\tgetPoolSize: ......... ").append(_scheduledExecutor.getPoolSize()).append('\n');
            list.append("\tgetLargestPoolSize: .. ").append(_scheduledExecutor.getLargestPoolSize()).append('\n');
            list.append("\tgetMaximumPoolSize: .. ").append(_scheduledExecutor.getMaximumPoolSize()).append('\n');
            list.append("\tgetCompletedTaskCount: ").append(_scheduledExecutor.getCompletedTaskCount()).append('\n');
            list.append("\tgetQueuedTaskCount: .. ").append(_scheduledExecutor.getQueue().size()).append('\n');
            list.append("\tgetTaskCount: ........ ").append(_scheduledExecutor.getTaskCount()).append('\n');
            list.append("ThreadPoolExecutor\n");
            list.append("=================================================\n");
            list.append("\tgetActiveCount: ...... ").append(_executor.getActiveCount()).append('\n');
            list.append("\tgetCorePoolSize: ..... ").append(_executor.getCorePoolSize()).append('\n');
            list.append("\tgetPoolSize: ......... ").append(_executor.getPoolSize()).append('\n');
            list.append("\tgetLargestPoolSize: .. ").append(_executor.getLargestPoolSize()).append('\n');
            list.append("\tgetMaximumPoolSize: .. ").append(_executor.getMaximumPoolSize()).append('\n');
            list.append("\tgetCompletedTaskCount: ").append(_executor.getCompletedTaskCount()).append('\n');
            list.append("\tgetQueuedTaskCount: .. ").append(_executor.getQueue().size()).append('\n');
            list.append("\tgetTaskCount: ........ ").append(_executor.getTaskCount()).append('\n');
            return list;
        }
    }
}
